/************************************************
 * Copyright (c) 2007 ~ 2009, 
 * All rights reserved.
 * Version   : 1.0
 * Author    : lengsh@gmail.com 
 * Date      : 2009.1.2
 ************************************************/

#ifndef  __NETPROXY_ICONNECTION__H__
#define  __NETPROXY_ICONNECTION__H__

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "Debug.h"
//define in <linux/in.h>
#define      IP_MTU    14

using namespace std;

namespace netproxy {
#define  DEAD_CHECK_TIME   60
class IConnection
{
	protected:
		int m_socket;
                string _rtable;
                int m_iCounts;
	public:
		long m_lLasttime;
                long m_lCurtime;
		bool m_bLive;
		int m_iKey;
		string m_sHostname;
		string m_sHostIP;
		int m_iPort;
  
		long getLastTime(){ return m_lLasttime; }
		long getCurrTime(){ return m_lCurtime;  }
		IConnection(const char *hname, int port, int ik, const char *sbk ):
			m_sHostname(hname), m_iPort(port)
	{
 //               m_iMTU_recv = 1448;
		m_iKey = ik;
		m_lLasttime = 0;
		m_bLive = false;
		m_socket = 0;
                m_iCounts = 0;
		if(sbk!=NULL)
		{
			char *p = (char *)sbk;
                        DEBUG2("  bkstring = ", sbk);
                        string sv;
			while( *p != '\0')
			{
                              DEBUG2("    ", (int)(*p));
                              if( *p != (char)',')
                              {
                                  sv.append(1, *p);
                              }
                              else
                              {
                                  int ibk = atoi(sv.c_str());
                                  sv = "";
                                  _rtable.append(1, (char)ibk);
                              }
                              p++;
			}
			if(sv.length() > 0)
			{
                                DEBUG2("  bk ID = ", sv.c_str());
				int ibk = atoi(sv.c_str());
				_rtable.append(1, (char)ibk);
			} 
		}                             
	}

		virtual ~IConnection(){  }
		virtual bool Connect() = 0;
		virtual bool ReConnect() = 0;
		virtual bool getStatus( int imax )
		{
			if(m_iCounts >= imax){
				DEBUG5("current request Counts = ", m_iCounts, " >= ( imax =", imax,"), so it should be reconnect!" );
				return false;
                        }
			if(m_bLive)
				return m_bLive;

			m_lCurtime = time(NULL);
			if(m_lLasttime < ( m_lCurtime - DEAD_CHECK_TIME))
			{
				disConnect();
				Connect();
				m_lLasttime = m_lCurtime;
			}
			return m_bLive;
		}
//		int SetMTUSize(int size){ size > 0 ? m_iMTU_recv = size : m_iMTU_recv = 1448; return m_iMTU_recv; }
		int GetBackLength() { return (int)_rtable.length(); }
		bool CheckBackup(int iMin, int iMax)
		{
			int j = (int)_rtable.length();
                        DEBUG4("check ", m_iKey , "'s backup, length = ",j); 
			for(int i=0; i<j; i++)
			{
				char c = (char) _rtable.at(i);
                                DEBUG4("\tbackup NO.", i+1, " = ", (int)c);   
				if( (int)c < iMin || (int)c > iMax)
					return false;
                                 
			} 
			return true;
		}
		int  GetNextBackup(int &trynum)
		{
			int j = (int)_rtable.length();
			trynum = trynum%j;		
			j = (int)_rtable.at(trynum);
			trynum++;
			return j; 
		}

		virtual int Proxy(const char *data, unsigned int dlen, char **wbuf,unsigned &wsize, unsigned &wbytes, bool bReply) = 0;
	protected:
		virtual void disConnect() = 0;
};

}
#endif  // __MEMCACHE_CONNECTION__H__
